package com.ruoyi.bizsys.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Arrays;
import java.util.Map;
import java.util.zip.CRC32;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.ruoyi.bizsys.domain.CustContactsRelative;
import com.ruoyi.bizsys.mapper.ApplyAppListMapper;
import com.ruoyi.bizsys.mapper.ApplyContactsMapper;
import com.ruoyi.bizsys.utils.BizConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.sign.Md5Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.bizsys.mapper.ApplyAppDataMapper;
import com.ruoyi.bizsys.domain.ApplyAppData;
import com.ruoyi.bizsys.service.IApplyAppDataService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import sun.security.provider.MD5;

import static com.alibaba.druid.util.MySqlUtils.getId;


/**
 * App数据池Service业务层处理
 *
 * @author african-loan
 * @date 2021-12-30
 */
@Service
public class ApplyAppDataServiceImpl extends ServiceImpl<ApplyAppDataMapper,ApplyAppData> implements IApplyAppDataService {


    @Autowired
    RedisCache redisCache;

    @Autowired
    ApplyAppDataMapper applyAppDataMapper;

    @Autowired
    ApplyAppListMapper applyAppListMapper;

    @Autowired
    ApplyContactsMapper applyContactsMapper;

    /**
     * 查询App数据池
     *
     * @param id App数据池ID
     * @return App数据池
     */
    @Override
    public ApplyAppData selectApplyAppDataById(Long id) {
        return this.getById(id);
    }

    /**
     * 查询App数据池列表
     *
     * @param applyAppData App数据池
     * @return App数据池
     */
    @Override
    public List<ApplyAppData> selectApplyAppDataList(ApplyAppData applyAppData) {
        return this.list(new QueryWrapper<>(applyAppData).last("order by id desc"));
    }

    /**
     * 新增App数据池
     *
     * @param applyAppData App数据池
     * @return 结果
     */
            @Override
    public int insertApplyAppData(ApplyAppData applyAppData) {
                                                                                                                                        applyAppData.setCreateTime(DateUtils.getNowDate());
                            return baseMapper.insert(applyAppData);
    }

    /**
     * 修改App数据池
     *
     * @param applyAppData App数据池
     * @return 结果
     */
            @Override
    public int updateApplyAppData(ApplyAppData applyAppData) {
                                                                                                                                        return baseMapper.updateById(applyAppData);
    }

    /**
     * 批量删除App数据池
     *
     * @param ids 需要删除的App数据池ID
     * @return 结果
     */
            @Override
    public int deleteApplyAppDataByIds(Long[] ids) {
        return baseMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除App数据池信息
     *
     * @param id App数据池ID
     * @return 结果
     */
    @Override
    public int deleteApplyAppDataById(Long id) {
        return baseMapper.deleteById(id);
    }

    @Override
    public String getAppIds(List<ApplyAppData> appDataList) {

        StringBuffer sb = new StringBuffer();

        //先将redis中存在的app查找出来
        for (int i = 0;i<appDataList.size();i++){
            Map<String, String> redisParam = buildRedisParam(appDataList.get(i));
            String value = redisCache.getCacheMapValue(Constants.APP_LIST+redisParam.get("key"), redisParam.get("hashKey"))+"";
            if(StringUtils.isNotBlank(value) && !"null".equals(value)){
                sb.append(value);
                sb.append(",");
                appDataList.remove(i);
                i--;
            }else{
                appDataList.get(i).setMd5(redisParam.get("md5"));
                appDataList.get(i).setKey(redisParam.get("key"));
                appDataList.get(i).setHashKey(redisParam.get("hashKey"));
            }
        }

        //再将剩下的批量插入数据库
        if(appDataList.size()>0){

            applyAppDataMapper.saveBatch(appDataList);
            String ids = insertRedis(appDataList);
            sb.append(ids);
            return sb.toString();
        }

        return sb.substring(0,sb.length()-1);
    }

    private String insertRedis(List<ApplyAppData> appDataList) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0;i<appDataList.size();i++){
            ApplyAppData applyAppData = appDataList.get(i);
            Map<String, String> redisData = buildRedisParam(applyAppData);
            redisCache.setCacheMapValue(Constants.APP_LIST+redisData.get("key"),redisData.get("hashKey"),applyAppData.getId()+"");
            sb.append(applyAppData.getId());
            sb.append(",");
        }
        return sb.substring(0,sb.length()-1);
    }

    @Override
    public void initRedis(String newTableName) {
        //加载newTableName
        redisCache.setCacheObject(Constants.APPLY_CONTACTS_NEW_TABLE,newTableName);

        //加载appData
        QueryWrapper<ApplyAppData> applyContactsQueryWrapper = new QueryWrapper<>();
        applyContactsQueryWrapper.select("id","app_name","app_version","package_name","version_name","md5");
        List<ApplyAppData> applyAppDataList = applyAppDataMapper.selectList(applyContactsQueryWrapper);
        insertRedis(applyAppDataList);
    }

    @Override
    public int deviceKeywordByLoanGuideline(List<Integer> ids) {
        return applyAppDataMapper.deviceKeywordByLoanGuideline(ids);
    }

    @Override
    public int deviceKeywordByBarCredit(List<Integer> ids) {
        return applyAppDataMapper.deviceKeywordByBarCredit(ids);
    }

    public Map<String,String> buildRedisParam(ApplyAppData applyAppData){
        Map<String,String> map = new HashMap<>();
        String md5 = getMd5AppStr(applyAppData);
        String key = hashKey(md5);
        String hashKey = BKDRHash(md5)+"";
        map.put("md5",md5);
        map.put("key",key);
        map.put("hashKey",hashKey);
        map.put("value",applyAppData.getId()+"");

        return map;
    }

    @Override
    public List<String> getByIds(String ids) {

        return applyAppDataMapper.getByIds(ids);
    }

    public String getMd5AppStr(ApplyAppData applyAppData){

        String appName = applyAppData.getAppName()==null?"":applyAppData.getAppName();
        String appVersion = applyAppData.getAppVersion()==null?"":applyAppData.getAppVersion();
        String packageName = applyAppData.getPackageName()==null?"":applyAppData.getPackageName();
        String versionName = applyAppData.getVersionName()==null?"":applyAppData.getVersionName();

        return Md5Utils.hash(appName+appVersion+packageName+versionName);
    }

    public static final Integer COUNT = 2500;
    public static String hashKey(String key){
        CRC32 crc32 = new CRC32();
        crc32.update(key.getBytes());
        return crc32.getValue()%COUNT+"";
    }

    public static int BKDRHash(String str){
        int seed = 131;
        int hash = 0;
        for (int i =0;i<str.length();i++){
            hash = (hash*seed)+str.charAt(i);
        }
        return (hash & 0x7FFFFFFF);
    }

}
